<?php

namespace App\Console\Commands;

use App\Common\Machine\PlayerQueue;
use App\Events\GameNextTurn;
use App\Models\Machine;
use Illuminate\Console\Command;

class CheckPlayerQueues extends Command
{
    /**
     * 命令名称及参数
     *
     * @var string
     */
    protected $signature = 'mall:check-player-queues';
    
    /**
     * 命令描述
     *
     * @var string
     */
    protected $description = '检查玩家排队';
    
    /**
     * 检查的频率，每次检查间隔的秒数
     * 和业务结合调整，暂定为7秒。轮到用户游戏时，客户端会倒数5秒，若用户未开始游戏，则取消排队
     *
     * @var int
     */
    protected $sleep = 7;
    
    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }
    
    /**
     * 执行命令
     */
    public function handle()
    {
        $this->daemon();
    }
    
    /**
     * 循环检查玩家队列
     */
    public function daemon()
    {
        while (true) {
            $machines = Machine::where([
                'device_status' => Machine::DEVICE_STATUS_IDLE,
                'is_display' => 1,
            ])->get();
            
            foreach ($machines as $machine) {
                $queue = new PlayerQueue($machine);
                
                $this->checkPlayerQueue($queue);
            }
            
            sleep($this->sleep);
        }
    }
    
    /**
     * 检查游戏机对应的玩家队列
     *
     * @param \App\Common\Machine\PlayerQueue $queue
     */
    protected function checkPlayerQueue($queue)
    {
        // 不存在排队玩家
        if (! $nextUserId = $queue->nextUserId()) {
            return;
        }
        
        $machine = $queue->machine;
        if ($machine->latest_user_id != $nextUserId) {
            // 广播事件：游戏进入下一局
            event(new GameNextTurn($machine));
        } else {
            // 清除空闲状态设备的最近一次玩家用户id，确保该玩家能收到下一轮的`GameNextTurn`通知
            Machine::where([
                'id' => $machine->id,
                'device_status' => Machine::DEVICE_STATUS_IDLE,
                'latest_user_id' => $machine->latest_user_id,
            ])->update(['latest_user_id' => 0]);
        }
        
        $this->releaseOccupancy($queue, $nextUserId);
    }
    
    /**
     * 解除非正常情况下，对游戏机开始权限的占用
     *
     * @param \App\Common\Machine\PlayerQueue $queue
     * @param int $userId
     */
    protected function releaseOccupancy($queue, $userId)
    {
        // 3个周期还未开始，则取消排队
        $timeout = $this->sleep * 3;
        
        if ($queue->isOccupied($userId, $timeout)) {
            $queue->releaseOccupancy();
        } else {
            $queue->markOccupancy($userId);
        }
    }
}
